2023.6.18 全結合型NNのサンプル【torch】
データセットにはsklearnが提供するフィッシャーのアイリスデータを利用
バッチの生成にはPyTorchのTensorDatasetとDataLoaderを利用
最適化にはPyTorchのOptimを利用
関連
code: 20230618NN_FC.py
import torch as pt
import torch.nn as nn
import torch.nn.functional as f
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
import torch.optim
import matplotlib.pyplot as plt
###
### NNの設計
###
class Net(nn.Module):
def __init__(self, n_input, n_hidden, n_output):
super().__init__()
self.lin1 = nn.Linear(n_input, n_hidden)
self.lin2 = nn.Linear(n_hidden, n_output)
self.relu = nn.ReLU()
self.softmax = nn.Softmax(dim=1)
def forward(self, x):
x = self.lin1(x)
x = self.relu(x)
x = self.lin2(x)
x = self.softmax(x)
return x
###
### データの準備
###
dataset = load_iris() # データセットの取得
# 特徴量と教師データをndarray型からtensor型に変換
# 特徴量はtorch.float型にする必要がある
# 教師データは後でonehot化するためにtorch.int64型とする(インデックスとして利用できる値)
# dataset -> X, y
X = torch.tensor(dataset'data', dtype=pt.float) # 特徴量 y = torch.tensor(dataset'target', dtype=pt.int64) # 教師データ # 訓練と検証用に分割
# X, y -> X_train, X_test , y_train, y_test
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size = 0.25,
random_state = 42
)
# 教師データについて、訓練用と検証用のonehot表現を生成
# y_train, y_test -> y_train_onehot, y_test_onehot
y_train_onehot = f.one_hot(y_train, num_classes=3).float()
y_test_onehot = f.one_hot(y_test, num_classes=3).float()
# TensorDatasetとDataLoaderを利用してバッチを生成する
# X_train, y_train -> TensorDataset -> DataLoader
data_train = torch.utils.data.TensorDataset(X_train, y_train_onehot)
batch_size = 10
data_loader = torch.utils.data.DataLoader(
dataset = data_train,
batch_size = batch_size,
shuffle = True,
)
###
### 訓練
###
n_input = 4 # アイリスデータの特徴量は4
n_hidden = 10 # 隠れ層(中間層)のノード数
n_output = 3 # アイリスデータは3種類
epochs = 10000
lr = 0.01
model = Net(n_input=n_input, n_hidden=n_hidden, n_output=n_output)
optimizer = torch.optim.SGD(model.parameters(), lr=lr)
loss_func = nn.MSELoss()
LOSS = []
print('Dataset: Iris')
print('input =', n_input, ', hidden =', n_hidden, ', output =', n_output)
print('batch size =', batch_size, ', optimizer = SGD, lr =', lr)
model.train() # モデルを訓練モードに設定
for epoch in range(1, epochs + 1):
for X, y in data_loader: # DataLoaderはイミュータブルオブジェクト
optimizer.zero_grad()
y_train_predict = model(X)
loss = loss_func(y, y_train_predict)
LOSS.append(loss.item())
loss.backward()
optimizer.step()
if epoch % (epochs // 10) == 0:
print('progress =', int(epoch / epochs * 100),'%, EPOCH =', epoch, ', loss ={:.3e}'.format(loss.item()))
###
### 損失関数のプロット
###
plt.plot(LOSS, label='loss function')
plt.grid()
plt.legend()
plt.show()
###
### 推定精度の評価
###
model.eval() # ネットを推論モードに設定(計算グラフを生成しない)
y_test_predict = model.forward(X_test)
y_test_predict_max_index = y_test_predict.max(dim=1)1 y_test_predict_compare = y_test_predict_max_index == y_test
y_test_predict_accuracy = \
y_test_predict_compare.sum() / len(y_test_predict_compare)
print('accuracy: ', y_test_predict_accuracy.item())
# torch.save(model, 'result.pth')